Change SSH Port
Changing the SSH port moves the SSH daemon (sshd) from the default TCP port 22 to a different port (for example 2581 or 2222). This reduces background noise from automated scanners and brute-force attempts that primarily target port 22, while keeping SSH available for legitimate administration.
Background and history
SSH standardized on port 22 in the 1990s and became the default remote administration method for Unix-like systems. As internet-exposed servers became common, automated scanners began continuously probing port 22. Port changes emerged as a practical hardening step to reduce low-effort scanning traffic, usually paired with stronger controls such as key-based authentication, restricted firewall access, and rate limiting.
Adoption and where it’s commonly used
Common in:
- VPS and cloud servers with public IPv4/IPv6 addresses
- WordPress and web servers that receive constant SSH scanning
- Small-to-medium fleets where per-host hardening is applied consistently
Maintained by
- Maintained by the OpenSSH project community (OpenSSH server
sshd).
Best when to use
- SSH is exposed to the internet and logs show persistent scanning attempts.
- You already enforce SSH keys (preferred) or have strong authentication and monitoring.
- You can keep a recovery path (cloud console/serial/KVM) in case of lockout.
- You want a quick noise-reduction step in a hardening baseline.
Not suitable when
- Automation or integrations assume port 22 and cannot be updated safely.
- You have no out-of-band recovery option and cannot tolerate any lockout risk.
- Central policy requires port 22 for standardized access and monitoring.
Compatibility notes
-
OpenSSH config is typically
/etc/ssh/sshd_config. Many modern systems also support drop-ins in/etc/ssh/sshd_config.d/*.conf. -
Service name differs by distro:
- Debian/Ubuntu:
ssh - RHEL/Fedora/Rocky/AlmaLinux:
sshd
- Debian/Ubuntu:
-
If SELinux is enforcing on RHEL-based systems, a custom SSH port may require an SELinux policy update.
-
If you use a cloud/provider firewall (security groups, VPS firewall, edge firewall), you must allow the new port there as well as on the host.
Follow the order exactly. Keep your existing SSH session open until you have verified a second session can log in using the new port. Validate SSH configuration before reloading. Ensure firewall rules allow the new port before changing sshd settings.
How it works
sshd listens on one or more TCP ports defined by Port directives. Firewalls must allow inbound TCP traffic to that port. When you change the port:
sshdmust be reloaded/restarted to listen on the new port.- Your firewall must allow the new port.
- Clients must connect using
ssh -p <port>.
Prerequisites
- A working SSH session to the server
- Root access or a sudo-capable user
- Host firewall installed and enabled (commonly UFW on Ubuntu/Debian)
- Optional but strongly recommended: out-of-band access (provider console/serial/KVM)
Safe pre-checks (read-only)
Confirm current SSH listening ports
sudo ss -tulpn | grep -E 'sshd|:22|:2581' || true
Expected if still on default:
- A
LISTENline containing:22forsshd
Confirm SSH service status
systemctl status ssh 2>/dev/null || systemctl status sshd
Check firewall state and current SSH rules
UFW example:
sudo ufw status verbose
Step-by-step: change to a new port safely
The example below uses port 2581. Replace it with your chosen port.
Step 1: Choose a port
Recommended rules:
- Use a port between
1024and65535 - Avoid ports already used by services on your host
- Keep it consistent across your fleet/runbooks
Check if the port is already in use:
sudo ss -tulpn | grep ':2581' || echo "Port 2581 not currently in use"
Step 2: Allow the new port in the firewall first
UFW (Ubuntu/Debian common)
sudo ufw allow 2581/tcp comment "SSH (new port)"
sudo ufw status numbered
If you restrict SSH to trusted IPs, prefer an allowlist rule instead of allowing from anywhere:
sudo ufw allow from 203.0.113.10 to any port 2581 proto tcp comment "SSH (trusted IP)"
If your VPS/cloud provider uses a separate firewall/security group, you must allow TCP 2581 there as well. Host firewall rules alone are not sufficient.
Step 3: Update OpenSSH server configuration
Prefer a drop-in file when supported.
Option A: Drop-in configuration (recommended where available)
sudo install -d -m 0755 /etc/ssh/sshd_config.d
sudo tee /etc/ssh/sshd_config.d/10-custom-port.conf >/dev/null <<'EOF'
Port 2581
EOF
Option B: Edit /etc/ssh/sshd_config directly
Backup first:
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
Edit:
sudo nano /etc/ssh/sshd_config
Set (or add) a single Port line:
Port 2581
If multiple Port lines exist, sshd may listen on multiple ports. Decide whether you want a temporary overlap (22 and 2581) or a single port, and keep the configuration explicit.
Step 4: Validate SSH configuration syntax before reloading
sudo sshd -t
If this prints nothing, the config syntax is valid. If it returns an error, fix the config before continuing.
Step 5: Reload SSH safely
Reload is preferred over restart when supported.
sudo systemctl reload ssh 2>/dev/null || sudo systemctl reload sshd
If reload is not available, restart:
sudo systemctl restart ssh 2>/dev/null || sudo systemctl restart sshd
Step 6: Confirm sshd is listening on the new port
sudo ss -tulpn | grep -E 'sshd.*:2581|:2581.*sshd' || true
You should see LISTEN entries for :2581.
Step 7: Test a new SSH session before closing the old one
From your local machine:
ssh -p 2581 your_username@your_server_ip
Keep the original session open until the new session works.
Step 8: Close port 22 after successful verification (optional)
Only do this after confirming the new port works.
sudo ufw deny 22/tcp comment "Disable default SSH port"
sudo ufw status numbered
SELinux considerations (RHEL-based systems)
If SELinux is enforcing, sshd may fail to bind to a non-standard port even if the firewall is open. Symptoms often include:
- Port allowed in firewall
- No
sshdlistener on the new port - Connection attempts time out or are refused
Check SELinux mode:
getenforce 2>/dev/null || true
If enforcing, allow the new SSH port (example for 2581):
sudo semanage port -a -t ssh_port_t -p tcp 2581 2>/dev/null || sudo semanage port -m -t ssh_port_t -p tcp 2581
Then reload SSH and re-check listeners:
sudo systemctl reload sshd 2>/dev/null || sudo systemctl restart sshd
sudo ss -tulpn | grep -E 'sshd.*:2581|:2581.*sshd' || true
semanage availabilityIf semanage is missing, install the SELinux management utilities package for your distribution (commonly policycoreutils-python-utils or equivalent), then re-run the port command.
Troubleshooting: cannot connect on the new port (example: 2581)
Use these checks in order.
1) Confirm the firewall rule exists (host firewall)
UFW example:
sudo ufw status verbose
You should see an allow rule for 2581/tcp.
2) Confirm sshd is actually listening on the new port
sudo ss -tulpn | grep sshd
If you do not see :2581:
- The
Port 2581setting was not applied (or is overridden) sshdfailed to reload/restart- SELinux is blocking the bind (RHEL-based systems)
Check effective config:
sudo sshd -T | grep -i '^port '
This output is authoritative for what sshd will use.
3) Confirm SSH service restarted cleanly
sudo systemctl status ssh 2>/dev/null || sudo systemctl status sshd
sudo journalctl -u ssh -n 200 --no-pager 2>/dev/null || true
sudo journalctl -u sshd -n 200 --no-pager 2>/dev/null || true
4) Confirm your provider firewall/security group allows the port
If the host firewall is correct and sshd is listening on :2581 but you still cannot connect from the internet, the most common cause is an upstream block:
- Cloud security group/firewall does not allow TCP 2581
- Provider edge firewall blocks custom ports by policy
- You are testing from a source network that is restricted
A quick on-server sanity check (local connectivity) can confirm sshd is reachable locally:
# Local connect test (runs on the server itself)
ssh -p 2581 localhost
If localhost works but remote does not, the issue is upstream of sshd (provider firewall, routing, or external network restrictions).
5) Check you used the correct client syntax
Correct:
ssh -p 2581 your_username@your_server_ip
Common mistakes:
- Swapping flag order or missing
-p - Connecting to the wrong IP (IPv6 vs IPv4)
- Connecting as
rootwhen root login is disabled
6) Confirm you did not create conflicting rules
If you use allowlisting for SSH, confirm your source IP is permitted. For UFW, numbered rules help with clarity:
sudo ufw status numbered
Recovery and rollback
Roll back SSH config to port 22 (console recommended)
If you have console/serial/KVM access:
- Remove or revert the change.
- Validate config.
- Reload SSH.
- Re-open port 22 temporarily if needed.
Drop-in rollback:
sudo rm -f /etc/ssh/sshd_config.d/10-custom-port.conf
sudo sshd -t
sudo systemctl reload ssh 2>/dev/null || sudo systemctl reload sshd
Re-open port 22 (UFW):
sudo ufw allow 22/tcp comment "SSH recovery"
sudo ufw status verbose
Emergency: disable UFW temporarily (only if necessary)
sudo ufw disable
Re-enable after fixing SSH:
sudo ufw enable
sudo ufw status verbose
Disabling the firewall on an internet-exposed server increases risk. Use it only as a short-lived recovery step and restore your rules immediately.
Security notes
Changing the SSH port reduces opportunistic scanning noise but does not replace core hardening:
- Prefer SSH keys over passwords and disable password authentication where feasible.
- Disable direct root SSH login and use a sudo-capable admin user.
- Restrict SSH to trusted IP ranges where possible.
- Add rate limiting and ban automation (for example, Fail2Ban).
- Monitor authentication logs and changes to SSH configuration.
Quick reference
Safe change sequence
| Phase | Command |
|---|---|
| -- | -- |
| Allow new port (UFW) | sudo ufw allow 2581/tcp |
| Set SSH port (drop-in) | sudo tee /etc/ssh/sshd_config.d/10-custom-port.conf |
| Validate config | sudo sshd -t |
| Reload SSH | sudo systemctl reload ssh || sudo systemctl reload sshd |
| Confirm listening | sudo ss -tulpn | grep sshd |
| Test login | ssh -p 2581 user@server |
| Disable port 22 (optional) | sudo ufw deny 22/tcp |
Key verification commands
sudo sshd -T | grep -i '^port '
sudo ss -tulpn | grep sshd
sudo ufw status verbose 2>/dev/null || true
systemctl status ssh 2>/dev/null || systemctl status sshd